/*
 * Copyright 2008. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the Apache License, Version 2.0. You
 * can find a copy of the license at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */

package com.sinai.mshab.visibility.rule;

import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.TextBoxBase;
import com.google.gwt.user.client.ui.Widget;

import com.sinai.mshab.visibility.VisibilityRule;

/**
 * Exercise the {@link ShowIfEqualText} {@link VisibilityRule}.
 * 
 * @author Arthur Kalmenson
 */
public class ShowIfEqualTextTst extends GWTTestCase {
	
	/**
	 * The visibility rule we'll be testing.
	 */
	private VisibilityRule<TextBoxBase, Widget, String> rule;

	/**
	 * Test to insure that when we use null constructor arguments, we'll get an
	 * {@link IllegalArgumentException}.
	 */
	public void testNullConstArgs() {

		// test various permutations.
		nullConstArgument(null, null, null);
		nullConstArgument(new TextBox(), null, null);
		nullConstArgument(null, "blah", null);
		nullConstArgument(null, null, new TextBox());
		nullConstArgument(new TextBox(), null, new PasswordTextBox());
	}

	/**
	 * We expect one of the arguments to be null and so an
	 * {@link IllegalArgumentException} should be thrown when we create a new
	 * {@link ShowIfEqualTextTst} is created.
	 * 
	 * @param parent
	 *            the parent widget.
	 * @param value
	 *            the trigger value.
	 * @param child
	 *            the child widget.
	 */
	private void nullConstArgument(TextBoxBase parent, String value,
			Widget child) {

		try {
			rule = new ShowIfEqualText(parent, value, child);
			fail("Should have failed");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that when the {@link ShowIfEqualText} rule is created that
	 * the parent and child widgets remain visible.
	 */
	public void testVisibilityAtCreation() {

		// set up the test.
		TextBox parent = new TextBox();
		TextBox child = new TextBox();
		rule = new ShowIfEqualText(parent, "", child);

		// make sure both text boxes are visible.
		assertTrue(parent.isVisible());
		assertTrue(child.isVisible());
	}

	/**
	 * Test to insure that when we put an empty value as the value, that the
	 * child widget appears.
	 */
	public void testEmptyValue() {

		// set up the test.
		TextBox parent = new TextBox();
		TextBox child = new TextBox();
		rule = new ShowIfEqualText(parent, "", child);

		// set the child to invisible and make sure that after running the rule
		// it is visible.
		child.setVisible(false);
		rule.execute();
		assertTrue(parent.isVisible());
		assertTrue(child.isVisible());
	}

	/**
	 * Test to insure that when the rule is set to a single value, and the
	 * parent widget is just created, that the child is invisible.
	 */
	public void testSingleValueNotVisible() {

		// set up the test.
		PasswordTextBox parent = new PasswordTextBox();
		TextBox child = new TextBox();
		rule = new ShowIfEqualText(parent, "blah", child);

		// make sure that the child is made invisible.
		rule.execute();
		assertTrue(parent.isVisible());
		assertFalse(child.isVisible());
	}

	/**
	 * Test to insure that when the text on the parent widget is changed to the
	 * required text that the child widget appears.
	 */
	public void testSingleValueChildBecomesVisible() {

		// set up the test.
		TextArea parent = new TextArea();
		TextBox child = new TextBox();
		rule = new ShowIfEqualText(parent, "blah", child);

		// make sure that the child is made invisible.
		rule.execute();
		assertTrue(parent.isVisible());
		assertFalse(child.isVisible());

		// change the text on the parent and fire the execute again since the
		// keyboard listener is not fired.
		parent.setText("blah");
		rule.execute();
		assertTrue(parent.isVisible());
		assertTrue(child.isVisible());
	}

	/**
	 * Test to insure that when the text on the parent widget is changed to one
	 * of many values, that the child widget appears.
	 */
	public void testMultipleValueChildBecomesVisible() {

		// set up the test.
		TextBox parent = new TextBox();
		PasswordTextBox child = new PasswordTextBox();
		rule = new ShowIfEqualText(parent, "blah", child);
		rule.addTrigger("test");
		rule.addTrigger("show");

		// make sure that the parent and child are visible even when we add
		// multiple triggers but haven't executed.
		assertTrue(parent.isVisible());
		assertTrue(child.isVisible());

		// make sure that the child is made invisible.
		rule.execute();
		assertTrue(parent.isVisible());
		assertFalse(child.isVisible());

		// change the text on the parent and fire the execute again since the
		// keyboard listener is not fired. Try various texts.
		parent.setText("test");
		rule.execute();
		assertTrue(parent.isVisible());
		assertTrue(child.isVisible());
		parent.setText("should disappear");
		rule.execute();
		assertTrue(parent.isVisible());
		assertFalse(child.isVisible());
		parent.setText("show");
		rule.execute();
		assertTrue(parent.isVisible());
		assertTrue(child.isVisible());
	}

	/**
	 * Test setting the parent widget null. We expect an
	 * {@link IllegalArgumentException} to be thrown.
	 */
	public void testSetNullParent() {
		rule = new ShowIfEqualText(new TextBox(), "blah", new TextBox());
		try {
			rule.setParentWidget(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that setting a valid parent widget works.
	 */
	public void testValidParent() {
		rule = new ShowIfEqualText(new TextBox(), "blah", new TextBox());
		PasswordTextBox passwordBox = new PasswordTextBox();
		rule.setParentWidget(passwordBox);
		assertEquals(passwordBox, rule.getParentWidget());
	}

	/**
	 * Test to insure that setting a null child widget throws an
	 * {@link IllegalArgumentException}.
	 */
	public void testSetNullChild() {
		rule = new ShowIfEqualText(new TextBox(), "blah", new TextBox());
		try {
			rule.setChildWidget(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that setting a valid child widget works.
	 */
	public void testValidChild() {
		rule = new ShowIfEqualText(new TextArea(), "blah", new TextBox());
		TextArea passwordBox = new TextArea();
		rule.setChildWidget(passwordBox);
		assertEquals(passwordBox, rule.getChildWidget());
	}

	/**
	 * Test to insure adding a null trigger results in an
	 * {@link IllegalArgumentException} being thrown.
	 */
	public void testAddNullTrigger() {
		rule = new ShowIfEqualText(new TextBox(), "blah", new TextBox());
		try {
			rule.addTrigger(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	@Override
	public String getModuleName() {
		return "com.sinai.mshab.MshabVisibility";
	}
}
